package edu.ucsd.cs110.mycity.model.data;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.util.EntityUtils;
import org.jivesoftware.smack.util.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

import edu.ucsd.cs110.mycity.MyCityMapActivity;
import edu.ucsd.cs110.mycity.controller.ViewController;
import edu.ucsd.cs110.mycity.controller.XMPPController;

public class FavoritesModel extends ArrayList<Favorite> {

	static HttpClient client = new DefaultHttpClient();
	static HttpPost post = new HttpPost(
			"http://cs110w-my-city.appspot.com/favorites");

	public FavoritesModel() {
		super();
	}

	public static List<BuddyFavorite> getFavoritesFor(String username,
			final Drawable defaultMarker, final MapView mapView) {
		final ArrayList<BuddyFavorite> l = new ArrayList<BuddyFavorite>();
		HttpGet get = new HttpGet(
				"http://cs110w-my-city.appspot.com/favorites?q="
						+ URLEncoder.encode(StringUtils
								.parseBareAddress(username)));
		try {
			HttpResponse response = client.execute(get);
			HttpEntity entity = response.getEntity();
			String data = EntityUtils.toString(entity);
			try {
				JSONObject myjson = new JSONObject(data);
				JSONArray array = myjson.getJSONArray("data");
				for (int i = 0; i < array.length(); i++) {
					JSONObject obj = array.getJSONObject(i);
					int longitude = new BigDecimal(
							(String) obj.getString("longitude")).intValue();
					int latitude = new BigDecimal(
							(String) obj.getString("latitude")).intValue();
					BuddyFavorite f = new BuddyFavorite(defaultMarker, mapView);
					f.setKey(Long.parseLong((String) obj.get("key")));
					f.setName((String) obj.getString("name"));
					f.setDescription((String) obj.get("description") + "\nby " + (String) obj.get("username"));
					f.setVisible(Boolean.parseBoolean((String) obj
							.get("visible")));
					GeoPoint p = new GeoPoint(latitude, longitude);
					f.setPoint(p);
					l.add(f);
				}
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return l;

	}
	
	public static List<AllFavorite> getAllFavorites(final Drawable defaultMarker,
			final MapView mapView) {
		ArrayList<AllFavorite> l = new ArrayList<AllFavorite>();
		HttpGet get = new HttpGet("http://cs110w-my-city.appspot.com/favorites?q=all");
		HttpResponse response = null;
		try {
			response = client.execute(get);
		} catch (ClientProtocolException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		} catch (IOException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		HttpEntity entity = response.getEntity();
		String data = null;
		try {
			data = EntityUtils.toString(entity);
		} catch (ParseException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		try {
			JSONObject myjson = new JSONObject(data);
			JSONArray array = myjson.getJSONArray("data");
			for (int i = 0; i < array.length(); i++) {
				JSONObject obj = array.getJSONObject(i);
				int longitude = new BigDecimal(
						(String) obj.getString("longitude")).intValue();
				int latitude = new BigDecimal(
						(String) obj.getString("latitude")).intValue();
				AllFavorite f = new AllFavorite(defaultMarker, mapView);
				f.setKey(Long.parseLong((String) obj.get("key")));
				f.setName((String) obj.getString("name"));
				f.setDescription((String) obj.get("description"));
				f.setVisible(Boolean.parseBoolean((String) obj
						.get("visible")));
				GeoPoint p = new GeoPoint(latitude, longitude);
				f.setPoint(p);
				l.add(f);
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return l;
	}

	public static List<Favorite> getMyFavorites(final Drawable defaultMarker,
			final MapView mapView) {
		ArrayList<Favorite> l = new ArrayList<Favorite>();
		HttpGet get = new HttpGet(
				"http://cs110w-my-city.appspot.com/favorites?q="
						+ URLEncoder.encode(StringUtils
								.parseBareAddress(XMPPController
										.getConnection().getUser())));
		try {
			HttpResponse response = client.execute(get);
			HttpEntity entity = response.getEntity();
			String data = EntityUtils.toString(entity);
			try {
				JSONObject myjson = new JSONObject(data);
				JSONArray array = myjson.getJSONArray("data");
				for (int i = 0; i < array.length(); i++) {
					JSONObject obj = array.getJSONObject(i);
					int longitude = new BigDecimal(
							(String) obj.getString("longitude")).intValue();
					int latitude = new BigDecimal(
							(String) obj.getString("latitude")).intValue();
					Favorite f = new Favorite(defaultMarker, mapView);
					f.setKey(Long.parseLong((String) obj.get("key")));
					f.setName((String) obj.getString("name"));
					f.setDescription((String) obj.get("description"));
					f.setVisible(Boolean.parseBoolean((String) obj
							.get("visible")));
					GeoPoint p = new GeoPoint(latitude, longitude);
					f.setPoint(p);
					l.add(f);
				}
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return l;

	}

	public static void save(final Favorite f) {
		Thread t = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub

				try {
					List nameValuePairs = new ArrayList(1);
					nameValuePairs.add(new BasicNameValuePair("key", f.getKey()
							.toString()));
					nameValuePairs.add(new BasicNameValuePair("username",
							StringUtils.parseBareAddress(XMPPController
									.getConnection().getUser())));
					nameValuePairs.add(new BasicNameValuePair("name", f
							.getName()));
					boolean v = f.isVisible();
					String b = Boolean.toString(v);
					nameValuePairs.add(new BasicNameValuePair("visible", b));
					nameValuePairs.add(new BasicNameValuePair("description", f
							.getDescription()));
					nameValuePairs.add(new BasicNameValuePair("latitude",
							Integer.toString(f.getPoint().getLatitudeE6())));
					nameValuePairs.add(new BasicNameValuePair("longitude",
							Integer.toString(f.getPoint().getLongitudeE6())));
					nameValuePairs
							.add(new BasicNameValuePair("action", "merge"));
					post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
					try {
						HttpResponse response = client.execute(post);
						Log.i("FavoritesModel", "Trying entity merge");
					} catch (ClientProtocolException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} finally {

				}

			}

		});
		t.start();
	}

	public static void deleteThread(final Favorite f) {
		try {
			List nameValuePairs = new ArrayList(1);
			nameValuePairs.add(new BasicNameValuePair("key", f.getKey()
					.toString()));
			nameValuePairs.add(new BasicNameValuePair("action", "delete"));
			post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			try {
				HttpResponse response = client.execute(post);
				Log.i("FavoritesModel", "Trying entity delete");
			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {

		}

	}
	
	public static void delete(Favorite f) {
		new DeleteFavoriteTask().execute(f);
	}

	static class DeleteFavoriteTask extends AsyncTask<Favorite, Void, Void> {

		@Override
		protected Void doInBackground(Favorite... params) {
			int count = params.length;
			for (int i = 0; i < count; i++) {
				FavoritesModel.deleteThread(params[i]);
			}
			return null;
		}
		
		@Override
		protected void onPostExecute(Void result) {
			MyCityMapActivity m = (MyCityMapActivity) ViewController.getMapScreen();
			m.drawMyFav();
		}

	}

	public static void put(final Favorite f) {
		Thread t = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub

				try {
					List nameValuePairs = new ArrayList(1);
					nameValuePairs.add(new BasicNameValuePair("username",
							StringUtils.parseBareAddress(XMPPController
									.getConnection().getUser())));
					nameValuePairs.add(new BasicNameValuePair("name", f
							.getName()));
					nameValuePairs.add(new BasicNameValuePair("description", f
							.getDescription()));
					nameValuePairs.add(new BasicNameValuePair("latitude",
							Integer.toString(f.getPoint().getLatitudeE6())));
					nameValuePairs.add(new BasicNameValuePair("longitude",
							Integer.toString(f.getPoint().getLongitudeE6())));
					nameValuePairs.add(new BasicNameValuePair("visible",
							Boolean.toString(f.isVisible())));
					nameValuePairs.add(new BasicNameValuePair("action", "put"));
					Log.i("FavoritesModel", Boolean.toString(f.isVisible()));
					post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
					try {
						HttpResponse response = client.execute(post);
						HttpEntity entity = response.getEntity();
						String data = EntityUtils.toString(entity);
						Log.i("FavoritesModel",
								"Getting new favorite persisted data: " + data);
						try {
							JSONObject myjson = new JSONObject(data);
							JSONArray array = myjson.getJSONArray("data");
							JSONObject obj = array.getJSONObject(0);
							f.setKey(Long.parseLong((String) obj.get("key")));
							Log.i("FavoritesMode", "Set new key: "
									+ f.getKey().toString());
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					} catch (ClientProtocolException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} finally {

				}

			}

		});

		t.run();

	}

}
